package com.digua.atools.tools;

import android.content.Context;

import androidx.annotation.StringRes;

import com.alibaba.fastjson.JSON;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @author:digua
 * @dat:2021/8/23
 * @description:Object工具类
 */
public class ObjUtil {
    /**
     * 判断两个数据是否一样
     *
     * @param o1
     * @param o2
     * @return
     */
    public static <T> boolean eqIgnoreCase(final T o1, final T o2) {
        return o1 == null || o2 == null ? eq(o1, o2) : o1.toString().equalsIgnoreCase(o2.toString());
    }

    /**
     * 判断两个数据是否一样
     *
     * @param o1
     * @param o2
     * @return
     */
    public static <T> boolean eq(final T o1, final T o2) {
        return o1 == o2 || (o1 != null && o1.equals(o2));
    }

    /**
     * 判断两个数据是否一样
     *
     * @param str
     * @param resId
     * @return
     */
    public static boolean eq(Context context, String str, @StringRes int resId) {
        String str1 = ResUtil.str(context, resId);
        return eq(str, str1);
    }

    /**
     * 判断两个数据是否一样
     *
     * @param resId1
     * @param resId2
     * @return
     */
    public static boolean eq(Context context, @StringRes int resId1, @StringRes int resId2) {
        if (resId1 == resId2) {
            return true;
        }
        return eq(ResUtil.str(context, resId1), ResUtil.str(context, resId2));
    }

    /**
     * 判断传入参数中是否有包含的
     *
     * @param o1
     * @param o2
     * @return
     */
    public static <T> boolean eqHas(final T o1, final T... o2) {
        if (o1 == null || o2 == null || o2.length <= 0) {
            return false;
        }
        for (T t : o2) {
            if (eq(o1, t)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断传入参数中是否有包含的
     *
     * @param str
     * @param resIds
     * @return
     */
    public static boolean eqHas(Context context, String str, @StringRes int... resIds) {
        if (str == null || resIds == null || resIds.length <= 0) {
            return false;
        }
        for (int resId : resIds) {
            if (eq(str, ResUtil.str(context, resId))) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断传入参数中是否有包含的
     *
     * @param resId
     * @param strs
     * @return
     */
    public static boolean eqHas(Context context, @StringRes int resId, String... strs) {
        if (resId == 0 || strs == null || strs.length <= 0) {
            return false;
        }
        String str = ResUtil.str(context, resId);
        for (String s : strs) {
            if (eq(str, s)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断传入参数中是否有包含的
     *
     * @param o1
     * @param o2
     * @return
     */
    public static <T> boolean eqIgnoreCaseHas(final T o1, final T... o2) {
        if (o1 == null || o2 == null || o2.length <= 0) {
            return false;
        }
        for (T t : o2) {
            if (eqIgnoreCase(o1, t)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 克隆对象
     *
     * @param t
     * @return
     */
    public static <T> T clone(final T t) throws Exception {
        if (t == null) {
            return null;
        }
        if (isBaseDataOrStr(t)) {
            return t;
        }
        T res = null;
        try {
            String json = JSON.toJSONString(t);
            res = (T) JSON.parseObject(json, t.getClass());
        } catch (Exception e) {
            throw e;
        }
        return res;
    }

    /**
     * 是否为基础数据类型
     *
     * @param t
     * @return
     */
    public static <T> boolean isBaseData(final T t) {
        return t instanceof Integer || t instanceof Double || t instanceof Boolean || t instanceof Float || t instanceof Byte || t instanceof Short || t instanceof Long || t instanceof Character;
    }

    /**
     * 是否为基础数据类型包含字符串
     *
     * @param t
     * @return
     */
    public static <T> boolean isBaseDataOrStr(final T t) {
        return t instanceof String || isBaseData(t);
    }

    /**
     * 是否为基础数据类型
     *
     * @param clz
     * @return
     */
    public static <T> boolean isBaseData(Class<T> clz) {
        return eqHas(clz.getSimpleName(),
                Integer.class.getSimpleName(),
                Double.class.getSimpleName(),
                Boolean.class.getSimpleName(),
                Float.class.getSimpleName(),
                Byte.class.getSimpleName(),
                Short.class.getSimpleName(),
                Long.class.getSimpleName(),
                Character.class.getSimpleName()
        );
    }

    /**
     * 是否为基础数据类型包含字符串
     *
     * @param clz
     * @return
     */
    public static <T> boolean isBaseDataOrStr(Class<T> clz) {
        return eqHas(clz.getSimpleName(), String.class.getSimpleName()) || isBaseData(clz);
    }

    /**
     * 比较两个数据的大小 如果其中一个值为空值，空为小, 当前仅支持基本数据类型
     *
     * @param t1
     * @param t2
     * @param <T>
     * @return 0:一样/相等；1：t1 > t2；-1：t1 < t2
     */
    public static <T> int compare(T t1, T t2) {
        if (eq(t1, t2)) {
            return 0;
        }
        if (t1 == null) {
            return -1;
        }
        if (t2 == null) {
            return 1;
        }
        if (isBaseDataOrStr(t1)) {
            return (t1 + "").compareTo(t2 + "");
        }
        return t1.toString().compareTo(t2.toString());
    }

    /**
     * 通过对象的属性名获取属性值
     *
     * @param t
     * @param attrName 属性名
     * @param <T>
     * @param <R>      返回数据类型
     * @return
     */
    public static <T, R> R getValByAttr(T t, String attrName) {

        return getValByAttr(t, attrName, null);
    }

    /**
     * 通过对象的方法名获取方法值
     *
     * @param t
     * @param methodName 方法名
     * @param param      对应方法所要传的参数
     * @param <T>
     * @param <R>        返回数据类型
     * @return
     */
    public static <T, R> R getValByMethod(T t, String methodName, Object... param) {

        return getValByMethod(t, methodName, null, param);
    }

    /**
     * 通过对象的属性名获取属性值
     *
     * @param t
     * @param attrName 属性名
     * @param defVal   默认值
     * @param <T>
     * @param <R>      返回数据类型
     * @return
     */
    public static <T, R> R getValByAttr(T t, String attrName, R defVal) {
        if (t == null || attrName == null || attrName.trim().length() <= 0) {
            return defVal;
        }
        try {
            //得到属性
            Field field = t.getClass().getDeclaredField(attrName);
            //打开私有访问
            field.setAccessible(true);
            return (R) field.get(t);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return defVal;
    }

    /**
     * 通过对象的方法名获取方法值
     *
     * @param t
     * @param methodName 方法名
     * @param defVal     默认值
     * @param param      对应方法所要传的参数
     * @param <T>
     * @param <R>        返回数据类型
     * @return
     */
    public static <T, R> R getValByMethod(T t, String methodName, R defVal, Object... param) {
        if (t == null || methodName == null || methodName.trim().length() <= 0) {
            return defVal;
        }
        try {
            for (Method method : t.getClass().getMethods()) {
                if (eq(method.getName(), methodName) && method.getTypeParameters().length == param.length) {
                    return (R) method.invoke(t, param);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return defVal;
    }
}
